<?php

namespace common\service;

use common\exception\LogicException;
use common\model\ChatModel;
use common\model\ChatUserModel;
use common\model\MediaModel;
use common\model\MessageModel;
use common\model\ChatUnreadMessageModel;
use common\model\MessageReplyModel;
use common\model\SystemNotifyMessageDetailModel;
use common\model\UrgeMessageMemberModel;
use common\model\UserModel;
use common\model\MessageTemplateModel;
use StringTemplate\Engine;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;
use Webman\Stomp\Client;

class MessageService
{
    /**
     * @var CentrifugalService
     */
    private $centrifugalService;

    // 单例工具类
    use SingletonTrait;


    public function __construct()
    {
        $this->centrifugalService = CentrifugalService::getInstance();
    }

    /**
     * 清除当前会话未读消息
     * @param $currentUserId
     * @param $filter
     * @param $param
     * @return int
     */
    public function clearMessageUnread($currentUserId, $filter, $param)
    {
        $chatUnreadMessageModel = model(ChatUnreadMessageModel::class);
//        $param['popup_delete'] = $param['popup_delete'] ?? 0;
        $filter['user_id'] = $currentUserId;
        // 附加时间限制
        $filter['created'] = $filter['created'] ?? ['elt', $param['delete_time'] ?? 0];
        if (!empty($param['notify_type_filter'])) {
            $filter['notify_type'] = $param['notify_type_filter'];
        }
        //删除本会话中所有未读消息
        $deleteRows = $chatUnreadMessageModel->where($filter)->find();
        if (empty($deleteRows)) {
            return 0;
        }
        \Webman\Stomp\Client::send('remove_unread_message', build_queue_data_with_xu([
            'filter' => $filter ?? [],
            'limit' => 100,
        ]));
        return 0;

//        if (!empty($param['notify_type_filter'])) {
//            $messageIdList = array_column($deleteRows, 'message_id');
//            $messageIdList = model(MessageModel::class)->where(['id' => ['IN', $messageIdList]])->where(['notify_type' => $param['notify_type_filter']])->column('id');
//            if (empty($messageIdList)) {
//                return 0;
//            }
//            $deleteRows = array_filter($deleteRows, function ($row) use ($messageIdList) {
//                return in_array($row['message_id'], $messageIdList);
//            });
//            if (empty($deleteRows)) {
//                return 0;
//            }
//        }
//        return $chatUnreadMessageModel
//            ->where([
//                'id' => ['IN', implode(',', array_column($deleteRows, 'id'))],
//            ])
//            ->delete();
    }

    /**
     * 发送消息
     * @param $param
     * @param $userId
     * @return array|bool
     * @throws Exception
     */
    public function sendMessage($param, $userId)
    {
        $chatGlobalId = $param['data']['chat_global_id'];
        $param['data']['sender'] = $userId;
        $messageModel = model(MessageModel::class);
        $messageReplyData = [];
        $updateMainMessageSql = "";

        $chat = model(ChatModel::class)->where(['global_id' => $chatGlobalId])->field("id,global_id,type,created_by,is_delete")->find();

        if (empty($chat)) {
            throw_strack_exception("missing chat data", ErrorCode::MISSING_CHAT_DATA);
        }

        if ($chat['is_delete'] === "yes") {
            throw_strack_exception("chat disbanded", ErrorCode::CHAT_DISBANDED);
        }

        //如果用户离开了不能再发送消息
        $chatUser = model(ChatUserModel::class)->where(['chat_global_id' => $chatGlobalId, 'user_id' => $userId])->find();
        if (empty($chatUser) || $chatUser['is_leave'] === "yes") {
            throw_strack_exception("you has left the chat", ErrorCode::YOU_HAS_LEFT_THE_CHAT);
        }

        switch ($param['data']['content_type']) {
            case "file":
                //处理media_server存储的消息体 自动生成media数据
                if ($param['data']['content']['storage_type'] == "media_server") {
                    $mediaItem = $param['data']['extra_file_media'] ?? [];
                    $mediaId = 0;
                    $mediaData = null;
                    if (!empty($mediaItem)) {
                        $mediaService = new MediaService();
                        $mediaModel = model(MediaModel::class);
                        $mediaService->generateMediaData($mediaItem);
                        $mediaData = $mediaModel->addItem($mediaItem);
                        if (!$mediaData) {
                            throw new LogicException($mediaModel->getError(), ErrorCode::MEDIA_ADD_FAILURE);
                        }
                        $mediaId = $mediaData['id'];
                    }
                    $param['data']['content']['media_id'] = $mediaId;
                    $param['data']['content']['media_data'] = $mediaData;
                }
                break;
            case 'reply':
                $replyMessageId = $param['data']['reply_message_id'];
                $replyMessage = $messageModel->find($replyMessageId);
                if (!$replyMessage) {
                    throw_strack_exception("The reply message data is incorrect", ErrorCode::MESSAGE_REPLY_FAILURE);
                }
                // 如果回复的消息是主消息的第一条回复,那么UUID必定为空，并且也没有消息组，需要在消息组表中创建一条数据的同时也将UUID更新给主消息
                // 如果有UUID那么回复的消息不一定是主消息，需要在消息组表中进行查找主消息ID
                if (empty($replyMessage['message_reply_id'])) {
                    $messageReplyData['message_main_id'] = $param['data']['reply_message_id'];
                    $messageReplyData['created_by'] = $userId;
                    $messageReply = model(MessageReplyModel::class)->addItem($messageReplyData);
                    if (!$messageReply) {
                        throw_strack_exception("The reply message data is incorrect", ErrorCode::MESSAGE_REPLY_FAILURE);
                    }
                    $updateMainMessageSql = "UPDATE message SET message_reply_id = '{$messageReply['id']}', content = JSON_SET(IFNULL(content, '{}'), '$.\"reply_sum\"', IFNULL(content ->> '$.reply_num', 0)+1) where id = {$messageReply['message_main_id']}";
                } else {
                    $messageReply = model(MessageReplyModel::class)->find($replyMessage['message_reply_id']);
                    $updateMainMessageSql = "UPDATE message SET content = JSON_SET(IFNULL(content, '{}'), '$.\"reply_sum\"', content->>'$.reply_sum'+1) where id = {$messageReply['message_main_id']}";
                }
                $param['data']['message_reply_id'] = $messageReply['id'];
                break;
        }

        $messageModel->startTrans();
        try {
            // 新增消息
            $addMessageResult = $messageModel->addItem($param['data']);
            if ($updateMainMessageSql) {
                $messageModel->execute($updateMainMessageSql);
            }
            // 处理文件消息
            if (!$addMessageResult) {
                throw new LogicException(model(MessageModel::class)->getError(), ErrorCode::ADD_NEW_MESSAGE_FAILURE);
            }
            // 回复消息需返回被回复消息体
            if ($param['data']['content_type'] == 'reply') {
                $addMessageResult['reply_message'] = $messageModel->findData(['filter' => ['id' => $param['data']['reply_message_id']]]);
                $addMessageResult['reply_message']['reply_main_message_id'] = $messageReply['message_main_id'];
                $addMessageResult['reply_message']['is_reply'] = true;
            }
            // 转发消息需返回所转发消息的集合
            if ($param['data']['content_type'] == 'forward') {
                $tmpForwardMessageIds = explode(",", $param['data']['content']['forward_message_ids']);
                sort($tmpForwardMessageIds); // 保存的消息ID顺序根据前端操作决定，需要按照正序排列
                $tmpForwardMessageIds = array_slice($tmpForwardMessageIds, 0, 5);
                $forwardMessage = $messageModel->selectData(['filter' => ['id' => ['IN', implode(',', $tmpForwardMessageIds)]], 'order' => ['sent_at asc']]);
                $addMessageResult['forward_message'] = $forwardMessage['rows'];
            }
            $messageModel->commit();
        } catch (\Throwable $e) {
            $messageModel->rollback();
            throw $e;
        }
        Client::send('send_message', build_queue_data_with_xu(['message_id' => $addMessageResult['id'], 'x-userinfo' => request()->getXUserInfo()]));
        return $addMessageResult;
    }

    /**
     * 获取用户姓名和头像
     * @param array $userIds
     * @return mixed
     */
    public function getChatUserInfo($userIds = [])
    {
        $userModel = model(UserModel::class);
        return $userModel->field('user.id,user.name,media.thumb,channel')
            ->join('media AS media ON media.link_id=user.id AND media.type="thumb" AND media.module="user"', 'LEFT')
            ->where(['user.id' => ['IN', implode(',', $userIds)]])
            ->select();
    }

    /**
     * 检查填入的消息模板参数，不存在的赋值为空
     * @param $param
     * @param $templateStr
     * @return array
     */
    protected function checkMsgTemplateParam($param, $templateStr)
    {
        $strPattern = "/(?<={)[^}]+/";
        $arrMatches = [];
        preg_match_all($strPattern, $templateStr, $arrMatches);

        $paramResult = [];
        if (!empty($arrMatches[0])) {
            foreach ($arrMatches[0] as $keyWord) {
                if (array_key_exists($keyWord, $param)) {
                    $paramResult[$keyWord] = $param[$keyWord];
                } else {
                    $paramResult[$keyWord] = '';
                }
            }
        } else {
            throw_strack_exception('The template is not standard.', ErrorCode::TEMPLATE_NOT_STANDARD);
        }

        return $paramResult;
    }

    /**
     * 渲染消息模板
     * @param $templateId
     * @param $param
     * @return array
     */
    public function renderMsgTemplate($templateId, $param)
    {
        // 获取消息模板配置
        $msgTemplateModel = model(MessageTemplateModel::class);
        $template = $msgTemplateModel->where(['id' => $templateId])->find();
        if (empty($template)) {
            throw_strack_exception('Message template does not exist.', ErrorCode::MESSAGE_TEMPLATE_NOT_EXIST);
        }
        $templateStr = $template['template'];
        $templatePcStr = $template['template_pc'];
        // 渲染消息模板
        $paramResult = $this->checkMsgTemplateParam($param, $templateStr);
        $engine = new Engine();
        $template['content_rendered'] = $engine->render($templateStr, $paramResult);
        $template['content_pc_rendered'] = $engine->render($templatePcStr, $paramResult);

        return $template;
    }

    /**
     * 发送系统通知消息
     * @param $data
     * @param array $detailMessages
     * @param string $notifyUserMark
     * @return array
     * @throws Exception
     */
    public function sendSystemNoticeMessage($data, $detailMessages = [], $notifyUserMark = "producer_assistant")
    {
        $noticeUser = UserService::getInstance()->getSystemNoticeUser($notifyUserMark);
        $receiver = $data['receiver'];
        $chatService = new ChatService();
        $chat = $chatService->getOneToOneChat($receiver, $noticeUser['id'], ['link_type' => $notifyUserMark, 'edited_at' => time()]);
        $data['chat_global_id'] = $chat['global_id'];

        $message = $this->sendMessage(['data' => $data], $noticeUser['id']);

        foreach ($detailMessages as $detailMessage) {
            $detailMessage['message_id'] = $message['id'];
            model(SystemNotifyMessageDetailModel::class)->addItem($detailMessage);
        }

        return $message;
    }

    /**
     * 批量发送系统通知
     * @param $data
     * @param $detailMessages
     * @param $notifyUserMark
     * @return array
     * @throws Exception
     */
    public function batchSendSystemNoticeMessage($data, $detailMessages = [], $notifyUserMark = "producer_assistant")
    {
        $noticeUser = UserService::getInstance()->getSystemNoticeUser($notifyUserMark);
        $receiver = $data['receiver'];
        $chatService = new ChatService();
        $chatList = $chatService->getOneToOneChatList($receiver, $noticeUser['id'], ['link_type' => $notifyUserMark, 'edited_at' => time()]);
        $res = [];
        foreach ($chatList as $chat) {
            $data['chat_global_id'] = $chat['global_id'];
            $message = $this->sendMessage(['data' => $data], $noticeUser['id']);
            $res[] = $message;
            foreach ($detailMessages as $detailMessage) {
                $detailMessage['message_id'] = $message['id'];
                model(SystemNotifyMessageDetailModel::class)->addItem($detailMessage);
            }
        }
        return $res;
    }

    /**
     * 旧版消息转换关系
     * @return array[]
     */
    public function getOldMessageRelation()
    {
        return [
            MessageModel::NOTIFY_TYPE_MESSAGE_TASK => [
                'notify_type' => ['task_remind', 'examine', 'todo'],
                'message_key' => [
                    'new_task_assigned',
                    'task_repaired',
                    'task_delay_review_result',
                    'task_upstream_done',
                    'step_category_task_assignee',
                    'not_started_task_statistics_daily',
                    'notify_task_member'
                ],
            ],
            MessageModel::NOTIFY_TYPE_MESSAGE_REVIEW => [
                'notify_type' => ['approval', 'examine'],
                'message_key' => [
                    'task_delay_order_need_review',
                    'task_delay_order_review_result',
                    'notify_party_b_to_accept_order',
                    'order_create_or_update_review_result_notify',
                    'task_version_need_review',
                    'task_delay_need_review',
                    'task_version_review_result'
                ]
            ],
            MessageModel::NOTIFY_TYPE_MESSAGE_PRODUCER => [
                'notify_type' => ['examine'],
                'message_key' => ['plan_confirm_review_result', 'plan_need_review']
            ],
            MessageModel::NOTIFY_TYPE_MESSAGE_DEMAND => [
                'notify_type' => ['task_remind'],
                'message_key' => [
                    'demand_has_new_comment',
                    'entity_close_operation',
                    'task_demand_change',
                    'entity_demand_change',
                    'episode_demand_change',
                    'task_close_operation'
                ]
            ],
        ];
    }

    /**
     * 消息列表 带已读状态
     * @param $param
     * @param $currentUserId
     * @param $isSelectReply
     * @return array
     */
    public function selectWithReadStatus($param, $currentUserId, $isSelectReply = true)
    {
        // chat_global_id一定要存在，防止全表扫码
        if (!isset($param['filter']['message.chat_global_id'])) {
            return [];
        }

        $messageModel = model(MessageModel::class);
        $order = $param['order'] ?? "message.sent_at desc";
        $page = $param['page'] ?? [1, 2];
        $fields = $param['fields'] ?? "message.*";
        $fieldsArray = explode(',', $fields);

        $messageTransList = $this->getOldMessageRelation();
        $messageNotifyTypeSubList = [];
        $messageMessageKeySubList = [];
        if (isset($param['filter']['message.notify_type']) && isset($messageTransList[$param['filter']['message.notify_type']])) {
            // 旧消息适配: 取出旧消息message_key 和 notify_type
            $messageNotifyTypeSubList = $messageTransList[$param['filter']['message.notify_type']]['notify_type'] ?? [];
            $messageMessageKeySubList = $messageTransList[$param['filter']['message.notify_type']]['message_key'] ?? [];
        }

        if (isset($param['filter']['message.message_key'])) {
            // 指定了messahg_key，则合并notify_type
            $param['filter']['message.content->>"$.message_key"'] = $param['filter']['message.message_key'];
            unset($param['filter']['message.message_key']);
            if (isset($param['filter']['message.notify_type'])) {
                $messageNotifyTypeSubList[] = $param['filter']['message.notify_type'];
            }
            if (!empty($messageNotifyTypeSubList)) {
                $param['filter']['message.notify_type'] = ['in', implode(',', $messageNotifyTypeSubList)];
            }
        } else {
            // 否则 取出notify_type，补充_or
            $subFilter = [];
            if (!empty($messageNotifyTypeSubList)) {
                $subFilter['message.notify_type'] = ['in', $messageNotifyTypeSubList];
            }
            if (!empty($messageMessageKeySubList)) {
                $subFilter['message.content->>"$.message_key"'] = ['in', $messageMessageKeySubList];
            }
            if (!empty($subFilter)) {
                $subFilter = [
                    '_logic' => 'or',
                    $subFilter,
                ];
                if (isset($param['filter']['message.notify_type'])) {
                    $subFilter['message.notify_type'] = $param['filter']['message.notify_type'];
                    unset($param['filter']['message.notify_type']);
                }
                $param['filter'][] = $subFilter;
            }
        }
        $data = $messageModel
            ->where($param['filter'])
            ->order($order)
            ->page($page[0], $page[1])
            ->field(implode(',', $fieldsArray))
            ->select();

        if (empty($data)) {
            return [
                'rows' => []
            ];
        }

        //催一催消息获取
        $messageIdList = [];

        $urgeMessageIds = [];
        $systemHitUrgeMessageIds = [];
        // 查询回复消息变量
        $replyMessageIdList = [];
        $replyMessageMap = [];
        $replySender = [];
        $replySenderList = [];
        $messageReplyIds = [];
        $replyMainMessageIds = [];
        $messageChatGlobalIds = array_column($data, 'chat_global_id');
        // 转发消息变量
        $forwardMessageIds = [];
        $forwardMessageMap = [];
        $forwardMessageSenderList = [];
        foreach ($data as $dataItem) {
            if ($isSelectReply) {
                if ($dataItem['content_type'] === 'reply' || $dataItem['reply_message_id'] > 0) {
                    $messageReplyIds[] = $dataItem['message_reply_id'];
                    if (!array_key_exists($dataItem['reply_message_id'], $messageIdList) && !in_array($dataItem['reply_message_id'], $replyMessageIdList)) {
                        $replyMessageIdList[] = $dataItem['reply_message_id'];
                    } else if (array_key_exists($dataItem['reply_message_id'], $messageIdList)) {
                        $replyMessageMap[$dataItem['reply_message_id']] = $messageIdList[$dataItem['reply_message_id']];
                    }
                }
            }
            $messageIdList[$dataItem['id']] = $dataItem;
            if ($dataItem['content_type'] == "urge") {
                $dataContent = json_decode($dataItem['content'], true) ?? [];
                if (!empty($dataContent["urge_message_id"])) {
                    $urgeMessageIds[] = $dataContent["urge_message_id"];
                }
            }
            if ($dataItem['content_type'] == "system_hint") {
                $dataContent = json_decode($dataItem['content'], true) ?? [];
                if (!empty($dataContent["type"]) && $dataContent["type"] == "urge_read" && !empty($dataContent["replace"]["urge_message_id"])) {
                    $systemHitUrgeMessageIds[] = $dataContent["replace"]["urge_message_id"];
                }
            }
            $tmpForwardMessageIds = [];
            $dataItem['content'] = json_decode($dataItem['content'], true);
            if ($dataItem['content_type'] == 'forward' && !empty($dataItem['content']['forward_message_ids'])) {
                $tmpForwardMessageIds = explode(",", $dataItem['content']['forward_message_ids']);
                sort($tmpForwardMessageIds); // 保存的消息ID顺序根据前端操作决定，需要按照正序排列
                $tmpForwardMessageIds = array_slice($tmpForwardMessageIds, 0, 5);
            }
            $forwardMessageIds = array_merge($forwardMessageIds, $tmpForwardMessageIds);
        }

        $isMyUrge = [];
        $urgeMessageMemberReceiverGroup = [];
        if (!empty($urgeMessageIds)) {
            $urgeMessageDetail = $this->getUrgeMessageDetail($urgeMessageIds, $currentUserId);
            $isMyUrge = $urgeMessageDetail['is_my_urge_message'];
            $urgeMessageMemberReceiverGroup = $urgeMessageDetail['urge_message_member_receiver_group'];
        }
        if (!empty($systemHitUrgeMessageIds)) {
            $urgeMessageMemberList = model(UrgeMessageMemberModel::class)
                ->where(["urge_message_id" => ["IN", $systemHitUrgeMessageIds], "user_id" => $currentUserId])->field("urge_message_id")->select();
            $systemHitUrgeMessageIds = array_column($urgeMessageMemberList, 'urge_message_id', 'urge_message_id');
        }

        // 回复消息
        if ($isSelectReply) {
            if (!empty($replyMessageIdList)) {
                $replyMessageData = $messageModel->where(['id' => ['IN', implode(',', $replyMessageIdList)]])->select();
                $replyMessageMap += array_column($replyMessageData, null, 'id');
            }
            // 获取每条回复消息的主消息
            if ($messageReplyIds) {
                $mainMessageList = model(MessageReplyModel::class)->where(['id' => ['IN', implode(',', $messageReplyIds)]])->field('id,message_main_id')->select();
                $replyMainMessageIds = array_column($mainMessageList, 'message_main_id', 'id');
            }
            // 获取不在同一会话中的回复消息发送人ID
            if ($replyMessageMap) {
                foreach ($replyMessageMap as $item) {
                    $replySender[] = $item['sender'];
                }
            }
            if ($replySender) {
                $replySenderList = model(UserModel::class)->field('id,name')->where(['id' => ['IN', implode(',', $replySender)]])->select();
                $replySenderList = array_column($replySenderList, 'name', 'id');
            }
        }
        // TODO 查询转发消息,不需要关联查询转发的消息里面的用户,预览转发消息只预览前五条
        if ($forwardMessageIds) {
            $forwardMessageList = $messageModel->where(['id' => ['IN', implode(',', $forwardMessageIds)]])->select();
            foreach ($forwardMessageList as &$item) {
                $item['content'] = json_decode($item['content'], true);
            }
            $forwardMessageMap = array_column($forwardMessageList, null, 'id');
            $forwardMessageSenderIds = array_column($forwardMessageList, 'sender');
            if ($forwardMessageSenderIds) {
                $forwardMessageSenderList = model(UserModel::class)->field('id,name')->where(['id' => ['IN', implode(',', $forwardMessageSenderIds)]])->select();
                $forwardMessageSenderList = array_column($forwardMessageSenderList, 'name', 'id');
            }
        }

        //查询未读消息
        $messageIdArray = array_column($data, 'id') + array_filter($replyMessageIdList);
        $unreadMessageIdList = model(ChatUnreadMessageModel::class)
            ->where([
                'message_id' => ['IN', implode(',', $messageIdArray)],
                'user_id' => $currentUserId,
            ])
            ->field("message_id")
            ->column('message_id');

        foreach ($replyMessageMap as &$replyMessageDatum) {
            $this->formatMessageData($replyMessageDatum, $unreadMessageIdList, $currentUserId, false);
        }

        foreach ($data as &$row) {
            $this->formatMessageData($row, $unreadMessageIdList, $currentUserId);
            if ($isSelectReply && ($row['content_type'] == 'reply' || $row['reply_message_id'] > 0)) {
                $row['reply_message'] = $replyMessageMap[$row['reply_message_id']] ?? null;
                $row['reply_message']['sender_name'] = $replySenderList[$replyMessageMap[$row['reply_message_id']]['sender']] ?? null;
                $row['reply_message']['reply_main_message_id'] = $replyMainMessageIds[$row['message_reply_id']] ?? 0;
                $row['reply_message']['is_reply'] = true;
            }
            if ($row['content_type'] == 'forward') {
                if (!empty($row['content']['forward_message_ids'])) {
                    $tmpForwardMessageIds = explode(",", $row['content']['forward_message_ids']);
                    foreach ($tmpForwardMessageIds as $forwardMessageId) {
                        if (array_key_exists($forwardMessageId, $forwardMessageMap)) {
                            // 预览合并转发消息体需要用户名称
                            if (empty($forwardMessageMap[$forwardMessageId]['sender_name'])) {
                                $forwardMessageMap[$forwardMessageId]['sender_name'] = $forwardMessageSenderList[$forwardMessageMap[$forwardMessageId]['sender']] ?? null;
                            }
                            $row['forward_message'][] = $forwardMessageMap[$forwardMessageId];
                        }
                    }
                    if (!empty($row['forward_message'])) {
                        array_multisort(array_column($row['forward_message'], 'sent_at'), SORT_ASC, $row['forward_message']);
                    }
                }
            }
            if ($row['content_type'] == 'urge') {
                if (!empty($row['content']["urge_message_id"])) {
                    $row['urge_message_user'] = $urgeMessageMemberReceiverGroup[$row['content']["urge_message_id"]] ?? null;
                    $row['is_show_urge'] = !empty($isMyUrge[$row['content']["urge_message_id"]]);
                }
            }
            //催一催系统性消息也只能催一催内部人员看到
            if ($row['content_type'] == "system_hint") {
                if (!empty($row['content']["type"]) && $row['content']["type"] == "urge_read" && !empty($row['content']["replace"]["urge_message_id"])) {
                    $row['is_show_urge'] = !empty($systemHitUrgeMessageIds[$row['content']["replace"]["urge_message_id"]]);
                }
            }
        }
        return [
//            'total' => $count,
            'rows' => $data
        ];
    }

    /**
     * 格式化消息数据
     * @param $row
     * @param $unChatIdArray
     * @param $currentUserId
     * @param $isCheckContent
     * @return void
     */
    public function formatMessageData(&$row, $unChatIdArray, $currentUserId, $isCheckContent = true)
    {
        $row['is_read'] = !in_array($row['id'], $unChatIdArray) ? 'yes' : 'no';
        $row['content'] = json_decode($row['content'], true);
        if ($isCheckContent && $row['status'] == "revoke" && $row['sender'] != $currentUserId) {
            $row['content'] = null;
        }
    }

    /**
     * 发送系统通知消息
     * @param array $param 渲染参数
     * @param int $receiver 接收人
     * @param int $messageTemplateId 消息模板id
     * @param string $contentType 内容类型
     * @param string $noticeIcon 通知icon
     * @param array $actions 操作
     * @param string $noticeType 提示类型
     * @param string $type 消息类型
     * @return mixed
     * @throws \Exception
     */
    public function sendSystemNoticeMessageForHuman($param, int $receiver, int $messageTemplateId, $contentType = "card_message", $noticeIcon = '', $actions = [], $noticeType = 'remind', $type = 'normal', $notifyUserMark = "producer_assistant")
    {

        $renderedTemplate = $this->renderMsgTemplate($messageTemplateId, $param);

        $data = [
            'receiver' => $receiver,
            'type' => $type,
            'content_type' => $contentType,
            'content' => [
                'title' => $renderedTemplate['title'],
                'content' => $renderedTemplate['content_rendered'],
                'content_pc' => $renderedTemplate['content_pc_rendered'],
                'type' => $noticeType,
                'urls' => $actions,
                'icon' => $noticeIcon
            ]
        ];

        $messageResult = $this->sendSystemNoticeMessage($data, [], $notifyUserMark);
        return $messageResult;
    }

    /**
     * 查询系统通知消息
     * @param $param
     * @param $userId
     * @return array
     * @throws \Exception
     */
    public function selectSystemNotifyMessage($param, $userId): array
    {

        // 系统会话列表查询
        $systemChatList = $this->getSystemChatList($userId);
        if (empty($systemChatList)) {
            return [
                'total' => 0,
                'rows' => []
            ];
        }

        $type = $param['type'] ?? "unread";
        $param['filter'] = $param['filter'] ?? [];
        $page = $param['page'] ?? [1, 20];
        $order = $param['order'] ?? "message.sent_at DESC";
        $filed = "message.id,message.global_id,message.chat_global_id,sender,sent_at,message.project_id,type,content,channel_id,content_type,is_popup,message.notify_type";

        $chatGlobalIdList = array_column($systemChatList, 'global_id', 'global_id');

        $chatGlobalIdStr = implode(',', $chatGlobalIdList);
        $chatGlobalIdStrWrapped = implode(',', array_map(function ($item) {
            return "'$item'";
        }, $chatGlobalIdList));
        if ($type == "unread") {
            $order = 'chat_unread_message.message_id desc';
            $messages = model(MessageModel::class)
                ->join("chat_unread_message ON chat_unread_message.message_id = message.id", "INNER")
                ->where($param['filter'])
                ->where(['chat_unread_message.chat_global_id' => ['IN', $chatGlobalIdStr]])
                ->where(['chat_unread_message.user_id' => $userId])
                ->field($filed)
                ->page($page[0], $page[1])
                ->order($order)
                ->select();
        } else {
            $messages = model(MessageModel::class)
                ->where($param['filter'])
                ->where(['chat_global_id' => ['IN', $chatGlobalIdStr]])
                ->where("message.id NOT IN (SELECT message_id from chat_unread_message where user_id = {$userId} AND chat_global_id IN ($chatGlobalIdStrWrapped))")
                ->field($filed)
                ->page($page[0], $page[1])
                ->order($order)
                ->select();
        }

        foreach ($messages as &$message) {
            $message['content'] = json_decode($message['content'], true);
            $message['is_read'] = $type != "unread" ? "yes" : "no";
        }
        return [
            'rows' => $messages
        ];
    }

    /**
     * 查询系统会话信息
     * @param $userId
     * @return array
     */
    private function getSystemChatList($userId): array
    {
        $noticeUsers = UserService::getInstance()->getSystemNoticeUser();
        $globalIdList = [];
        foreach ($noticeUsers as $noticeUser) {

            if ($userId > $noticeUser['id']) {
                $globalId = $noticeUser['id'] . '&' . $userId;
            } else {
                $globalId = $userId . '&' . $noticeUser['id'];
            }

            $globalIdList[] = $globalId;
        }
        if (empty($globalIdList)) {
            return [];
        }
        return model(ChatModel::class)->where(['global_id' => ['IN', implode(',', $globalIdList)]])->select();
    }

    /**
     * 清空所有未读消息
     * @param int $getUserId
     * @return false|int|mixed|string
     */
    public function clearAllUnRead(int $getUserId)
    {
        $ids = model(ChatUnreadMessageModel::class)
            ->alias('cum')
            ->join('message AS m on cum.message_id = m.id', 'LEFT')
            ->where([
                'm.is_popup' => 'no',
                'cum.user_id' => $getUserId,
            ])
            ->field("cum.id")
            ->group("cum.id")
            ->select();
        $ids = array_column($ids, 'id');
        $res = 0;
        if (!empty($ids)) {
            $res = model(ChatUnreadMessageModel::class)
                ->where(['id' => ["IN", implode(',', $ids)]])
                ->delete();
        }

        return $res;
    }

    /**
     * 推送消息 添加未读消息 支持限制接收用户
     * @param $messageId
     * @throws \Exception
     */
    public function sendMessageAsync($messageId, $notifierRestrictList = [])
    {
        $message = model(MessageModel::class)->find($messageId);
        if (empty($message)) {
            throw_strack_exception('message not found', ErrorCode::MESSAGE_NOT_FOUND);
        }
        $message = CommonService::getFormatAttrData(model(MessageModel::class), $message);
        $chat = model(ChatModel::class)->where(['global_id' => $message['chat_global_id']])->find();
        //通过chat_global_id取出会话成员

        if ($chat['link_type'] === 'task_work_order') {
            $queueData = [
                'x-userinfo' => request()->getXUserInfo(),
                'global_id' => $chat['global_id'],
                'sent_at' => $message['sent_at'],
            ];
            Client::send('update_work_order_assistant_edited_at', json_encode($queueData));
        }
        ChatService::getInstance()->updateChatEditedAt($chat['id'], $message['sent_at']);

        $chatUserUserIdListFilter = [
            'chat_global_id' => $chat['global_id'],
            'is_leave' => "no",
            'user_id' => ['neq', $message['sender']],
        ];
        $chatUserUserIdList = model(ChatUserModel::class)->where($chatUserUserIdListFilter)->field('user_id')->select();
        $receivers = array_column($chatUserUserIdList, 'user_id', 'user_id');
        $receiverChannels = [];
        if (!empty($receivers)) {
            $notifiers = $receivers;
            if (!empty($notifierRestrictList)) {
                $notifiers = array_intersect($receivers, $notifierRestrictList);
            }
            $receiverChannels = model(UserModel::class)->where(['id' => ['IN', $notifiers]])->field('id,channel')->select();
            $receiverChannels = array_column($receiverChannels, 'channel', 'id');
        }


        //更新常用联系人,记录用户最近的联系人,异步处理
        if ($chat['type'] === 'one2one') {
            //有系统会话用户不记录

            $systemUsers = model(UserModel::class)->where(['is_system' => 'yes'])->field('id')->select();
            $systemUsers = array_column($systemUsers, 'id');
            $isSystemChat = false;
            if (!empty($systemUsers)) {
                $chatUserList = $receivers;
                $chatUserList[] = $message['sender'];
                $isSystemChat = !empty(array_intersect($chatUserList, $systemUsers));
            }
            if (!$isSystemChat) {
                Client::send('save_frequent_contacts', build_queue_data_with_xu([
                    'chat_global_id' => $chat['global_id'],
                    'sent_at' => $message['sent_at'],
                ]));
            }
        }

        $unreadMessages = [];
        //新增未读消息
        if (!empty($receivers)) { //存在接收人
            foreach ($receivers as $receiverId) {
                // 排除自己ID
                // 如果存在则不添加(针对稍后提醒)
                if ($receiverId != $message['sender']) {
                    $unreadMessages[] = [
                        'user_id' => $receiverId,
                        'chat_global_id' => $chat['global_id'],
                        'message_id' => $messageId,
                        'notify_type' => $message['notify_type'] ?? '',
                        'created' => time(),
                    ];
                }
            }
            if (count($unreadMessages) > 0) {
                // 批量添加未读消息记录
                model(ChatUnreadMessageModel::class)->addAll($unreadMessages);
            }
        }

        $chat['avatar'] = [];
        if ($chat['type'] == "one2one") {
            $userAvatar = $this->getChatUserInfo([$message['sender']]);
            if (empty($userAvatar)) {
                $chat['name'] = "没有名字";
                $chat['avatar'] = [];
            } else {
                $chat['name'] = $userAvatar[0]['name'];
                $chat['avatar'] = $userAvatar[0]['thumb'] ? [$userAvatar[0]['thumb']] : [];
            }
        } else if ($chat['type'] == "group") {
            $userAvatar = $this->getChatUserInfo(array_slice($receivers, 0, 9, false));
            $chat['avatar'] = array_column($userAvatar, 'thumb');
        }
        $chat['chat_global_id'] = $chat['global_id'];
        // 发送回复消息需返回回复消息体
        if (!empty($message['reply_message_id']) && $message['reply_message_id'] > 0) {
            $message['reply_message'] = model(MessageModel::class)->findData(['filter' => ['id' => $message['reply_message_id']]]);
            if (!empty($message['message_reply_id']) && $message['message_reply_id'] > 0) {
                $messageReply = model(MessageReplyModel::class)->find($message['message_reply_id']);
                $message['reply_message']['reply_main_message_id'] = $messageReply['message_main_id'];
                $message['reply_message']['is_reply'] = true;
            }
        }
        // 合并转发消息需返回消息集合
        if ($message['content_type'] == 'forward') {
            $forwardMessageIds = explode(',', $message['content']['forward_message_ids']);
            sort($forwardMessageIds);
            $forwardMessageIds = array_slice($forwardMessageIds, 0, 5);
            $message['forward_message'] = model(MessageModel::class)->where(['id' => ['IN', implode(',', $forwardMessageIds)]])->order('sent_at asc')->select();
            if ($message['forward_message']) {
                $forwardMessageSenderIdList = array_column($message['forward_message'], 'sender');
                $messageSenderList = model(UserModel::class)->where(['id' => ['IN', $forwardMessageSenderIdList]])->select();
                $messageSenderList = array_column($messageSenderList, 'name', 'id');
                foreach ($message['forward_message'] as &$item) {
                    $item['content'] = json_decode($item['content'], true);
                    $item['sender_name'] = $messageSenderList[$item['sender']];
                }
            }
        }
        $pushMessage = [
            'message' => $message,
            'chat' => $chat
        ];
        // 特殊处理@操作  强制ding用户
        $dingRemind = false;
        $dingRemindUsers = [];

        if (isset($message['content']['type']) && in_array($message['content']['type'], ['remind_specified_user', 'remind_all'])) {
            $dingRemind = true;
            $contentType = $message['content']['type'];
            if ($contentType == "remind_all") {
                $dingRemindUsers = $receivers;
            }
            if ($contentType == "remind_specified_user") {
                $remindUserId = $message['content']['user_id'] ?? "";
                $dingRemindUsers = explode(',', $remindUserId);
            }
        }

        // 标记会话 chatUser 为 by@ 有人@我
        if (count($dingRemindUsers) > 0) {
            $dingRemindUsersFilter = [
                'user_id' => ['IN', implode(',', $dingRemindUsers)],
                'chat_global_id' => $chat['global_id']
            ];
            $chatUsers = model(ChatUserModel::class)->where($dingRemindUsersFilter)->field('id')->select();
            if (count($chatUsers) > 0) {
                $chatUserIdList = array_column($chatUsers, 'id', 'id');
                $chatUserIdStr = implode(',', $chatUserIdList);
                // 使用update json_set  批量更新
                model(ChatUserModel::class)->execute("UPDATE chat_user SET config = JSON_SET(IFNULL(config, '{}'), '$.\"by@\"', 'yes') where id in ($chatUserIdStr)");
            }
        }

        try {
            // 拆分ding消息和普通消息推送
            $specialDingMessageChannels = [];
            $dingCount = 0;
            $normalCount = 0;
            $broadCastChannels = [];
            foreach ($receiverChannels as $uid => $receiverChannel) {
                if ($dingRemind && in_array($uid, $dingRemindUsers)) {
                    $dingCount += 1;
                    $specialDingMessageChannels[] = $receiverChannel;
                } else {
                    $broadCastChannels[] = $receiverChannel;
                    $normalCount += 1;
                }
            }

            // 推送普通消息通知
            $pushMessage['ding'] = false;
            if ($normalCount > 1) {
                $this->centrifugalService->broadcast($broadCastChannels, $pushMessage);
            } else if ($normalCount === 1) {
                $this->centrifugalService->pushMassage(array_shift($broadCastChannels), $pushMessage);
            }

            // 推送@消息通知
            $pushMessage['ding'] = true;
            if ($dingCount > 1) {
                $this->centrifugalService->broadcast($specialDingMessageChannels, $pushMessage);
            } else if ($dingCount === 1) {
                $this->centrifugalService->pushMassage(array_shift($specialDingMessageChannels), $pushMessage);
            }

        } catch (\Throwable $e) {
            trace(format_exception_info($e), 'ERR');
            //推送失败 不需要告诉前端
        }
    }

    /**
     * 推送新会话通知
     * @param $chatId
     * @param $receivers
     * @param $currentUserId
     * @throws \Exception
     */
    public function pushNewChatMessage($chatId, $receivers, $currentUserId)
    {
        $chat = ChatService::getInstance()->getChatDetail(['id' => $chatId]);
        $adminUser = model(UserModel::class)->field('id,name')->find($currentUserId);
        $receiverUserInfo = $this->getChatUserInfo($receivers);
        //创建群聊,推送一条消息,不记录此消息
        $tmpMessage = [
            "chat_global_id" => $chat['global_id'],
            "type" => 'normal',
            'sender' => 0,
            'project_id' => 0,
            "content_type" => 'system_hint',
            "content" => [
                "type" => "create_chat",
                "replace" => [
                    "admin" => $adminUser,
                    "receiver" => $receiverUserInfo
                ]
            ]
        ];

        $chat['avatar'] = [];
        if ($chat['type'] == "one2one") {
            $userAvatar = $this->getChatUserInfo([$currentUserId]);
            if (empty($userAvatar)) {
                $chat['name'] = "没有名字";
                $chat['avatar'] = [];
                $chat['chat_icon_data'][] = [];
            } else {
                $chat['name'] = $userAvatar[0]['name'];
                $avatar = $userAvatar[0]['thumb'] ? [$userAvatar[0]['thumb']] : [];
                $chat['avatar'] = $avatar;
                $chat['chat_icon_data'][] = [
                    "id" => $userAvatar[0]['id'],
                    "name" => $userAvatar[0]['name'],
                    "avatar" => $avatar
                ];
            }
        } else if ($chat['type'] == "group") {
            $userAvatar = array_slice($receiverUserInfo, 0, 9, false);

            $chat['avatar'] = array_column($userAvatar, 'thumb');
            foreach ($userAvatar as $userAvatarItem) {
                $chat['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $chat['count'] = count($receivers);
        }
        $chat['chat_global_id'] = $chat['global_id'];

        if ($chat['type'] == "one2one") {
            model(ChatModel::class)->where(['id' => $chat['id']])->save(['edited_at' => time()]);
        } else if ($chat['type'] == "group") {
            // 如果当前是工单会话 就通知所有人的工单小助手
            $receiveUserList = model(UserModel::class)->field('id,channel')->where(['id' => ['IN', $receivers]])->select();
            APP_DEBUG && trace(var_export($chat, true), 'DEBUG');
            if ($chat['link_type'] === 'task_work_order') {
                $workOrderMessage = [
                    "chat_global_id" => $chat['global_id'],
                    "type" => 'normal',
                    'sender' => 0,
                    'project_id' => 0,
                    "content_type" => 'system_hint',
                    "content" => [
                        "type" => "create_work_order_chat",
                        "replace" => [
                            "admin" => $adminUser,
                            "receiver" => $receiverUserInfo
                        ]
                    ]
                ];
                // 推送一条工单会话通知
                $queueData = [
                    'chat_global_id' => $chat['global_id'],
                    'message' => $workOrderMessage,
                    'user_id_list' => array_column($receiveUserList, 'id'),
                    'is_update' => false,
                ];
                Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));

            }

            $queueData = [
                'chat_global_id' => $chat['global_id'],
                'message' => $tmpMessage,
                'user_id_list' => array_column($receiveUserList, 'id'),
                'is_update' => false,
            ];
            Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));
        }
    }

    /**
     * 工单会话，推送通知
     * @param $data
     * @param $currentUserId
     * @return bool
     * @throws \Exception
     */
    public function pushWorkOrderChatMessage($data, $currentUserId)
    {
        $chat = ChatService::getInstance()->getChatDetail(['global_id' => $data['global_id']]);
        if (empty($chat)) {
            throw_strack_exception('global_id not find', ErrorCode::GLOBAL_ID_NOT_FIND);
        }
        $receiverUserInfo = $this->getChatUserInfo($data['receives']);
        $contentExtraData = $data['content_extra_data'] ?? [];
        // 消息模板
        $tmpMessage = [
            "chat_global_id" => $chat['global_id'],
            "type" => 'normal',
            'sender' => 0,
            'project_id' => 0,
            "content_type" => 'system_hint',
            "content" => [
                    "type" => $data['content_type'],
                    "replace" => [
                        "admin" => model(UserModel::class)->field('id,name')->find($currentUserId),
                        "receiver" => $receiverUserInfo
                    ],
                ] + $contentExtraData
        ];
        if ($data['content_type'] == "add_work_order_executor" || $data['content_type'] == "del_work_order_executor") {
            $executorList = model(UserModel::class)->field('id,name')->where(['id' => ['IN', implode(',', $data['executor_ids'])]])->select();
            $tmpMessage['content']['replace']['executor'] = $executorList;
        }

        $userAvatar = array_slice($receiverUserInfo, 0, 9, false);
        foreach ($userAvatar as $userAvatarItem) {
            $chat['chat_icon_data'][] = [
                "id" => $userAvatarItem['id'],
                "name" => $userAvatarItem['name'],
                "avatar" => $userAvatarItem['thumb']
            ];
        }

        $chat['count'] = count($data['receives']);
        $chat['avatar'] = array_column($userAvatar, 'thumb');
        $receiveUserList = model(UserModel::class)->field('id,channel')->where(['id' => ['IN', $data['receives']]])->select();

        $queueData = [
            'chat_global_id' => $chat['global_id'],
            'message' => $tmpMessage,
            'user_id_list' => array_column($receiveUserList, 'id'),
        ];
        Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));
        return true;
    }

    /**
     * 批量推送工单会话通知
     * @param $data
     * @param $currentUserId
     * @return void
     * @throws \Exception
     */
    public function pushBatchWorkOrderChatMessage($data, $currentUserId)
    {
        $receives = []; // 所有的接收人id
        $chatMessage = [];
        $editedAtData = []; // 更新时间
        $chatDataExtra = [];
        $admin = model(UserModel::class)->field('id,name')->find($currentUserId);
        $userIds = $this->execBathReceiverIds($data);
        $receiverUserInfo = $this->getChatUserInfo($userIds);
        $receiverUserIds = array_column($receiverUserInfo, null, 'id');
        $chats = ChatService::getInstance()->getChatDetailAll(['global_id' => ['in', array_column($data, 'chat_global_id')]]);
        if (empty($chats)) {
            return;
        }
        $chatGlobalIds = array_column($chats, null, 'chat_global_id');
        foreach ($data as $value) {
            $receiver = [];
            $currentReceiver = [];
            foreach ($value['receiver'] as $userValue) {
                if (!isset($receiverUserIds[$userValue])) {
                    continue;
                }
                $receiver[] = $receiverUserIds[$userValue];
                $receives[] = $userValue;
                $currentReceiver[] = $userValue;
            }
            $value['receiver'] = $currentReceiver;
            // 处理消息模板
            $messageOne = [
                "chat_global_id" => $value['chat_global_id'],
                "type" => 'normal',
                'sender' => 0,
                'project_id' => 0,
                "content_type" => 'system_hint',
                "content" => [
                    "type" => $value['content_type'],
                    "replace" => [
                        "admin" => $admin,
                        "receiver" => $receiver
                    ],
                    "status" => $value['status']
                ]
            ];

            // 处理 chat_icon_data 最多展示9个头像
            $userAvatar = array_slice($receiver, 0, 9, false);
            foreach ($userAvatar as $userAvatarItem) {
                $chatDataExtra[$value['chat_global_id']]['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $chatDataExtra[$value['chat_global_id']]['count'] = count($value['receiver']);
            $chatDataExtra[$value['chat_global_id']]['avatar'] = array_column($userAvatar, 'thumb');
            // 消息模板
            $message = model(MessageModel::class)->addItem($messageOne);
            $chatMessage[$value['chat_global_id']] = $message;
            //添加消息未读
            $unreadMessages = [];
            //新增未读消息
            $receivers = array_column($receiver, 'id');
            if (!empty($receivers)) { //存在接收人
                foreach ($receivers as $receiverId) {
                    $unreadMessages[] = [
                        'user_id' => $receiverId,
                        'chat_global_id' => $value['chat_global_id'],
                        'message_id' => $message['id'],
                        'notify_type' => $message['notify_type'] ?? '',
                        'created' => time(),
                    ];
                }
                if (!empty($unreadMessages)) {
                    // 批量添加未读消息记录
                    model(ChatUnreadMessageModel::class)->addAll($unreadMessages);
                }
            }
            $editedAtData[] = ['id' => $chatGlobalIds[$value['chat_global_id']]['id'], 'edited_at' => $message['sent_at']];
            unset($receiver);
            unset($unreadMessages);
        }

        $chats = ChatService::getInstance()->getChatDetailAll(['global_id' => ['in', array_column($data, 'chat_global_id')]]);
        $chatGlobalIds = array_column($chats, null, 'chat_global_id');

        $workOrderChatFromTenantId = [];
        foreach ($chats as $chatValue) {
            if ($chatValue['link_type'] != 'task_work_order') {
                continue;
            }
            $workOrderChatFromTenantId[] = $chatValue['from_tenant_id'];
        }

        // 处理工单会话
        if (!empty($workOrderChatFromTenantId)) {
            // 过滤租户id
            $receiveUserChat = model(UserModel::class)->alias('u')
                ->join('tenant_user tu on tu.user_id = u.id')
                ->where(['tu.tenant_id' => ['IN', $workOrderChatFromTenantId]])
                ->where(['u.id' => ['IN', $receives]])
                ->where('tu.status = "active"')
                ->where("u.channel != ''")
                ->field('u.*')
                ->group('u.id')
                ->select();
            $receiveUserChannelList = array_column($receiveUserChat, 'channel', 'channel');
            foreach ($data as $value) {
                $chatData = $chatGlobalIds[$value['chat_global_id']];
                $chatData['count'] = $chatDataExtra[$value['chat_global_id']]['count'];
                $chatData['avatar'] = $chatDataExtra[$value['chat_global_id']]['avatar'];
                $chatData['chat_icon_data'] = $chatDataExtra[$value['chat_global_id']]['chat_icon_data'];
                $pushMessage = [
                    'chat' => $chatData,
                    'message' => $chatMessage[$value['chat_global_id']]
                ];
                $receiveUserChannelList = array_values($receiveUserChannelList);
                $this->centrifugalService->broadcast($receiveUserChannelList, $pushMessage);
            }
        }
        //update chat edited_at
        model(ChatModel::class)->saveAll($editedAtData);
    }

    /**
     * 处理接收者id
     * @param $data
     * @return array
     */
    public function execBathReceiverIds($data)
    {
        $userIds = [];
        foreach ($data as $userValues) {
            foreach ($userValues['receiver'] as $v) {
                $userIds[] = $v;
            }
        }
        return $userIds;
    }

    /**
     * 批量推送群聊创建消息
     * @param $chatIds
     * @param $chatReceivers
     * @param $chatCurrentUserId
     * @param $userId
     * @throws \Exception
     */
    public function batchPushNewChatMessage($chatIds, $chatReceivers, $chatCurrentUserId, $userId)
    {
        $chats = model(ChatModel::class)->where(['id' => ["IN", $chatIds]])->select();
        $userList = $this->getChatUserInfo($userId);
        $userIdList = array_column($userList, null, 'id');
        $chatMessage = [];
        $oneToOneChatIds = [];
        $channelUserIds = [];
        foreach ($chats as $chatIndex => $chat) {
            //一对一不推送消息
            if ($chat['type'] == "one2one") {
                $oneToOneChatIds[] = $chat['id'];
                unset($chatReceivers[$chat['global_id']], $chat[$chatIndex]);
                continue;
            }

            $currentChatReceivers = [];
            //不存在会话成员接收跳过
            if (!isset($chatReceivers[$chat['global_id']])) {
                unset($chatReceivers[$chat['global_id']], $chat[$chatIndex]);
                continue;
            }
            foreach ($chatReceivers[$chat['global_id']] as $chatReceiver) {
                if (isset($userIdList[$chatReceiver])) {
                    $currentChatReceivers[] = $userIdList[$chatReceiver];
                    $channelUserIds[] = $chatReceiver;
                }
            }

            //没有会话成员跳过
            if (empty($currentChatReceivers)) {
                unset($chat[$chatIndex]);
                continue;
            }

            //创建群聊,推送一条消息
            $chatMessage[$chat['global_id']] = [
                "chat_global_id" => $chat['global_id'],
                "type" => 'normal',
                "sender" => 0,
                "project_id" => 0,
                "content_type" => 'system_hint',
                "sent_at" => $chat['created'], //默认未群聊的创建时间
                "content" => [
                    "type" => "create_chat",
                    "replace" => [
                        "admin" => $userIdList[$chatCurrentUserId[$chat['global_id']]],
                        "receiver" => $currentChatReceivers
                    ]
                ]
            ];

            $chats[$chatIndex]['avatar'] = [];
            $chats[$chatIndex]['chat_global_id'] = $chat['global_id'];
            $userAvatar = array_slice($currentChatReceivers, 0, 9, false);
            $chats[$chatIndex]['avatar'] = array_column($userAvatar, 'thumb');
            foreach ($userAvatar as $userAvatarItem) {
                $chats[$chatIndex]['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $chats[$chatIndex]['count'] = count($currentChatReceivers);
        }
        $channelUserIds = array_unique($channelUserIds);

        //一对一的只需要更新最新更新时间
        if (!empty($oneToOneChatIds)) {
            model(ChatModel::class)->where(['id' => ['IN', $oneToOneChatIds]])->save(['edited_at' => time()]);
        }

        if (empty($channelUserIds)) {
            return;
        }

        $channelUserList = model(UserModel::class)->field('id,channel')->where(['id' => ['IN', $channelUserIds]])->select();
        $channelUserList = array_column($channelUserList, 'channel', 'id');
        $this->batchPushSystemHitMessage($chatMessage, $chatReceivers, $channelUserList, $chats, false);
    }

    /**
     * 更改群名
     * @param $chatData
     * @param $userId
     * @throws \Exception
     */
    public function pushUpdateChatNameMessage($chatData, $userId)
    {
        $adminUser = model(UserModel::class)->field('id,name')->find($userId);

        $channelList = model(ChatUserModel::class)
            ->alias('cu')
            ->join('user AS u ON cu.user_id = u.id', "LEFT")
            ->field('u.channel,cu.user_id,u.id')
            ->where(['chat_global_id' => $chatData['global_id'], 'cu.is_leave' => "no"])
            ->select();

        if (!empty($channelList)) {
            $userIds = array_column($channelList, 'user_id');
            $userAvatar = $this->getChatUserInfo(array_slice($userIds, 0, 9, false));
            $chatData['avatar'] = array_column($userAvatar, 'thumb');
            foreach ($userAvatar as $userAvatarItem) {
                $chatData['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $chatData['count'] = count($userIds);
            $tmpMessage = [
                "chat_global_id" => $chatData['global_id'],
                "type" => 'normal',
                'sender' => 0,
                'project_id' => 0,
                "content_type" => 'system_hint',
                "content" => [
                    "type" => "change_chat_name",
                    "replace" => [
                        "admin_user" => $adminUser,
                        "chat_name" => $chatData['name']
                    ]
                ]
            ];
            $queueData = [
                'chat_global_id' => $chatData['global_id'],
                'message' => $tmpMessage,
                'user_id_list' => $userIds
            ];
            Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));

        }
    }

    /**
     * 发送解除群的消息
     * @param $chat
     * @throws \Exception
     */
    public function pushDisbandChatMessage($chat)
    {
        $receiveUserChat = model(ChatUserModel::class)
            ->alias('cu')
            ->join('user AS u ON cu.user_id = u.id', "LEFT")
            ->field('u.channel,cu.user_id,u.id')
            ->where([
                'cu.chat_global_id' => $chat['global_id'],
                'cu.is_leave' => "no"
            ])->select();

        if (!empty($receiveUserChat)) {
            $userIds = array_column($receiveUserChat, 'user_id');
            $userAvatar = $this->getChatUserInfo(array_slice($userIds, 0, 9, false));
            $chat['avatar'] = array_column($userAvatar, 'thumb');
            foreach ($userAvatar as $userAvatarItem) {
                $chat['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $chat['count'] = count($userIds);
            $tmpMessage = [
                "chat_global_id" => $chat['global_id'],
                "type" => 'normal',
                'sender' => 0,
                'project_id' => 0,
                "content_type" => 'system_hint',
                "content" => [
                    "type" => "disband_chat"
                ]
            ];
            $queueData = [
                'chat_global_id' => $chat['global_id'],
                'message' => $tmpMessage,
                'user_id_list' => $userIds
            ];
            Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));

            //清空该群的所有人的未读消息
            model(ChatUnreadMessageModel::class)->where(['chat_global_id' => $chat['global_id']])->delete();
        }
    }

    /**
     * 批量发送解除群的消息
     * @param $chats
     * @return array|void
     * @throws \Exception
     */
    public function pushBathDisbandChatMessage($chats)
    {
        $receiveUserChatGlobals = $this->getUserChatGlobals($chats);
        if (empty($receiveUserChatGlobals)) {
            return [];
        }
        $chatReceivers = []; // 普通会话接收者用户id
        $workOrderFromTenantIds = []; // 工单会话接受租户id
        $workOrderChatReceivers = []; // 工单会话接收用户id
        $updateChatEditedDtData = []; // 更新会话时间
        // 处理所有发送消息信息
        $messageInfo = $this->getMessageInfo($chats);
        // 群头像
        $chatInfo = $this->getChatIconData($chats, $receiveUserChatGlobals);
        foreach ($chats as $value) {
            // 针对工单会话 过滤接收人
            if ($value['link_type'] === 'task_work_order') {
                $workOrderFromTenantIds[] = $value['from_tenant_id'];
                $workOrderChatReceivers[] = array_column($receiveUserChatGlobals[$value['chat_global_id']], 'user_id');
            } else {
                $chatReceivers = array_column($receiveUserChatGlobals[$value['chat_global_id']], 'user_id');
            }
        }
        // 工单会话消息推送
        if (!empty($workOrderChatReceivers)) {
            $receiveUserChatChannelList = $this->getWorkOrderChatChannel($workOrderChatReceivers, $workOrderFromTenantIds);
            $this->pushChatToBroadcast($chats, $chatInfo, $messageInfo, $receiveUserChatChannelList);
        }
        // 普通会话消息推送
        if (!empty($chatReceivers)) {
            $receiveUserChatChannelList = model(UserModel::class)->field('id,channel')->where(['id' => ['IN', $chatReceivers]])->select();
            $this->pushChatToBroadcast($chats, $chatInfo, $messageInfo, $receiveUserChatChannelList);
        }
        foreach ($messageInfo as $value) {
            $updateChatEditedDtData[] = ['id' => $value['chat_id'], 'edited_at' => $value['sent_at']];
        }
        // 批量更新群聊更新时间
        model(ChatModel::class)->saveAll($updateChatEditedDtData);
        // 清空该群的所有人的未读消息
        model(ChatUnreadMessageModel::class)->where(['chat_global_id' => ['IN', array_column($chats, 'global_id')]])->delete();
    }

    /**
     * 批量推送消息
     * @param $chats
     * @param $chatInfo
     * @param $messageInfo
     * @param $receiveUserList
     */
    public function pushChatToBroadcast($chats, $chatInfo, $messageInfo, $receiveUserList)
    {
        $receiveUserChannelList = array_column($receiveUserList, 'channel', 'channel');
        foreach ($chats as $value) {
            if (!empty($messageInfo[$value['chat_global_id']]['chat_id'])) {
                unset($messageInfo[$value['chat_global_id']]['chat_id']);
            }
            if (!empty($receiveUserChannelList)) {
                $chat = $chatInfo[$value['chat_global_id']] + $value;
                $pushMessage = [
                    'chat' => $chat,
                    'message' => $messageInfo[$value['chat_global_id']]
                ];
                $receiveUserChannelList = array_values($receiveUserChannelList);
                $this->centrifugalService->broadcast($receiveUserChannelList, $pushMessage);
            }
        }
    }

    /**
     * 批量获取工单会话通道
     * @param $workOrderChatReceivers // 工单会话接收者id
     * @param $workOrderFromTenantIds // 工单会话租户id
     * @return array|mixed|string
     */
    public function getWorkOrderChatChannel($workOrderChatReceivers, $workOrderFromTenantIds)
    {
        $uid = [];
        foreach ($workOrderChatReceivers as $workOrderChatReceiverValue) {
            foreach ($workOrderChatReceiverValue as $v) {
                $uid[] = $v;
            }
        }
        $receiveUserChat = model(UserModel::class)
            ->alias('u')
            ->join('tenant_user tu on tu.user_id = u.id')
            ->where(['tu.tenant_id' => ['IN', $workOrderFromTenantIds]])
            ->where('tu.status = "active"')
            ->where(['u.id' => ['IN', $uid]])
            ->field('u.*')
            ->group('u.id')
            ->select();
        if (empty($receiveUserChat)) {
            return [];
        }
        return $receiveUserChat;
    }

    /**
     * 批量获取chat用户信息
     * @param $chats
     * @return array
     */
    public function getUserChatGlobals($chats)
    {
        $receiveUserChat = model(ChatUserModel::class)
            ->alias('cu')
            ->join('user AS u ON cu.user_id = u.id', "LEFT")
            ->field('u.channel,cu.user_id,u.id,cu.chat_global_id')
            ->where([
                'cu.chat_global_id' => ['in', array_column($chats, 'global_id')],
                'cu.is_leave' => "no"
            ])->select();
        $receiveUserChatGlobals = [];
        foreach ($receiveUserChat as $value) {
            $receiveUserChatGlobals[$value['chat_global_id']][] = $value;
        }
        if (empty($receiveUserChatGlobals)) {
            return [];
        }
        return $receiveUserChatGlobals;
    }

    /**
     * 批量处理群头像
     * @param $chats
     * @param $receiveUserChatGlobals
     * @return array
     */
    public function getChatIconData($chats, $receiveUserChatGlobals)
    {
        $chatInfo = [];
        foreach ($chats as $value) {
            // 群头像最多展示9个
            $userIds = array_column($receiveUserChatGlobals[$value['chat_global_id']], 'user_id');
            $userAvatar = $this->getChatUserInfo(array_slice($userIds, 0, 9, false));
            $avatarData = [];
            foreach ($userAvatar as $userAvatarItem) {
                $avatarData[] = trim($userAvatarItem['thumb']);
                $chatInfo[$value['chat_global_id']]['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => trim($userAvatarItem['thumb']),
                ];
            }
            $chatInfo[$value['chat_global_id']]['avatar'] = $avatarData;
            $chatInfo[$value['chat_global_id']]['count'] = count($userIds);
        }
        return $chatInfo;
    }

    /**
     * 获取保存消息信息
     * @param $chats
     * @return array
     * @throws \Exception
     */
    public function getMessageInfo($chats)
    {
        $messageInfo = [];
        foreach ($chats as $value) {
            $tmpMessage = [
                "chat_global_id" => $value['global_id'],
                "type" => 'normal',
                'sender' => 0,
                'project_id' => 0,
                "content_type" => 'system_hint',
                "content" => [
                    "type" => "disband_chat"
                ]
            ];
            $messageInfo[$value['chat_global_id']] = model(MessageModel::class)->addItem($tmpMessage);
            $messageInfo[$value['chat_global_id']]['chat_id'] = $value['id'];
        }
        if (empty($messageInfo)) {
            return [];
        }
        return $messageInfo;
    }

    /**
     * 踢出用户
     * @param $adminUser
     * @param $chatGlobalId
     * @param $chatUsersIds
     * @param $channelList
     * @throws \Exception
     */
    public function pushDeleteChatUseMessage($adminUser, $chatGlobalId, $chatUsersIds, $channelList)
    {
        $leaveUser = model(UserModel::class)->where(['id' => ['IN', join(',', $chatUsersIds)]])->field('id,name')->select();
        $chat = ChatService::getInstance()->getChatDetail(['global_id' => $chatGlobalId]);
        $adminUser = model(UserModel::class)->field('id,name')->find($adminUser);

        if (!empty($channelList)) {
            $userIds = array_column($channelList, 'user_id');
            $userAvatar = $this->getChatUserInfo(array_slice($userIds, 0, 9, false));
            $chat['avatar'] = array_column($userAvatar, 'thumb');
            foreach ($userAvatar as $userAvatarItem) {
                $chat['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $chat['count'] = count($userIds);
            $tmpMessage = [
                "chat_global_id" => $chatGlobalId,
                "type" => 'normal',
                'sender' => 0,
                'project_id' => 0,
                "content_type" => 'system_hint',
                "content" => [
                    "type" => "delete_chat_user",
                    "replace" => [
                        "admin" => $adminUser,
                        "leave_user" => $leaveUser
                    ]
                ]
            ];
            $queueData = [
                'chat_global_id' => $chat['global_id'],
                'message' => $tmpMessage,
                'user_id_list' => $userIds
            ];
            Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));
        }
    }

    /**
     * 自行退出
     * @param $userId
     * @param $chatGlobalId
     * @throws \Exception
     */
    public function pushDeleteAndExitMessage($userId, $chatGlobalId)
    {
        $leaveUser = model(UserModel::class)->field('id,name')->find($userId);
        $chat = ChatService::getInstance()->getChatDetail(['global_id' => $chatGlobalId]);

        $channelList = model(ChatUserModel::class)
            ->alias('cu')
            ->join('user AS u ON cu.user_id = u.id', "LEFT")
            ->field('u.channel,u.id')
            ->where(['chat_global_id' => $chatGlobalId, 'cu.is_leave' => "no"])
            ->select();

        if (!empty($channelList)) {
            $userIds = array_column($channelList, 'user_id');
            $userAvatar = $this->getChatUserInfo(array_slice($userIds, 0, 9, false));
            $chat['avatar'] = array_column($userAvatar, 'thumb');
            foreach ($userAvatar as $userAvatarItem) {
                $chat['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $chat['count'] = count($userIds);
            $tmpMessage = [
                "chat_global_id" => $chatGlobalId,
                "type" => 'normal',
                'sender' => 0,
                'project_id' => 0,
                "content_type" => 'system_hint',
                "content" => [
                    "type" => "exit_chat_user",
                    "replace" => [
                        "leave_user" => $leaveUser
                    ]
                ]
            ];
            $queueData = [
                'chat_global_id' => $chat['global_id'],
                'message' => $tmpMessage,
                'user_id_list' => $userIds
            ];
            Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));
        }
    }

    /**
     * 转让群主
     * @param $userId
     * @param $newAdminUserId
     * @param $chatGlobalId
     * @throws \Exception
     */
    public function pushTransferAdminMessage($userId, $newAdminUserId, $chatGlobalId)
    {
        $oldAdminUser = model(UserModel::class)->field('id,name')->find($userId);
        $newAdminUser = model(UserModel::class)->field('id,name')->find($newAdminUserId);
        $chat = ChatService::getInstance()->getChatDetail(['global_id' => $chatGlobalId]);
        $channelList = model(ChatUserModel::class)
            ->alias('cu')
            ->join('user AS u ON cu.user_id = u.id', "LEFT")
            ->field('u.channel,u.id')
            ->where(['chat_global_id' => $chatGlobalId, 'cu.is_leave' => "no"])
            ->select();

        if (!empty($channelList)) {
            $userIds = array_column($channelList, 'user_id');
            $userAvatar = $this->getChatUserInfo(array_slice($userIds, 0, 9, false));
            $chat['avatar'] = array_column($userAvatar, 'thumb');
            foreach ($userAvatar as $userAvatarItem) {
                $chat['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $chat['count'] = count($userIds);
            $tmpMessage = [
                "chat_global_id" => $chatGlobalId,
                "type" => 'normal',
                'sender' => 0,
                'project_id' => 0,
                "content_type" => 'system_hint',
                "content" => [
                    "type" => "transfer_admin",
                    "replace" => [
                        "old_admin_user" => $oldAdminUser,
                        "new_admin_user" => $newAdminUser
                    ]
                ]
            ];
            $queueData = [
                'chat_global_id' => $chat['global_id'],
                'message' => $tmpMessage,
                'user_id_list' => $userIds
            ];
            Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));
        }
    }

    /**
     * 邀请用户
     * @param $chatGlobalId
     * @param $currentUser
     * @param $inviteUser
     * @throws \Exception
     */
    public function pushInviteChatUser($chatGlobalId, $currentUser, $inviteUser)
    {
        if (!empty($inviteUser)) {
            $currentUser = model(UserModel::class)->where(['id' => $currentUser])->field('id,name')->find();
            $chat = ChatService::getInstance()->getChatDetail(['global_id' => $chatGlobalId]);
            $inviteUser = model(UserModel::class)->where(['id' => ["IN", $inviteUser]])->field('id,name')->select();
            $userIds = array_column($inviteUser, 'user_id');
            $userAvatar = $this->getChatUserInfo(array_slice($userIds, 0, 9, false));
            $chat['avatar'] = array_column($userAvatar, 'thumb');
            foreach ($userAvatar as $userAvatarItem) {
                $chat['chat_icon_data'][] = [
                    "id" => $userAvatarItem['id'],
                    "name" => $userAvatarItem['name'],
                    "avatar" => $userAvatarItem['thumb']
                ];
            }
            $receiveUserChat = model(ChatUserModel::class)
                ->alias('cu')
                ->join('user AS u ON cu.user_id = u.id', "LEFT")
                ->field('cu.user_id,u.channel,u.id')
                ->where([
                    'cu.chat_global_id' => $chatGlobalId,
                    'cu.is_leave' => "no"
                ])->select();

            $chat['count'] = count($receiveUserChat);
            $tmpMessage = [
                "chat_global_id" => $chatGlobalId,
                "type" => 'normal',
                'sender' => 0,
                'project_id' => 0,
                "content_type" => 'system_hint',
                "content" => [
                    "type" => "invite_chat_user",
                    "replace" => [
                        "admin" => $currentUser,
                        "leave_user" => $inviteUser
                    ]
                ]
            ];
            $queueData = [
                'chat_global_id' => $chat['global_id'],
                'message' => $tmpMessage,
                'user_id_list' => array_column($receiveUserChat, 'user_id')
            ];
            Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));
        }
    }

    /**
     * 发送会话系统提示消息
     * @param $tmpMessage
     * @param $receiveUserList
     * @param $chat
     * @param $isUpdate
     * @return void
     * @throws \Exception
     */
    public function pushSystemHitMessage($tmpMessage, $receiveUserList, $chat, $isUpdate = true)
    {
        if (empty($receiveUserList) || empty($tmpMessage)) {
            return;
        }
        $message = model(MessageModel::class)->addItem($tmpMessage);
        //添加消息未读
        $unreadMessages = [];
        //新增未读消息
        $receivers = array_column($receiveUserList, 'id');
        if (!empty($receivers)) { //存在接收人
            foreach ($receivers as $receiverId) {
                $unreadMessages[] = [
                    'user_id' => $receiverId,
                    'chat_global_id' => $chat['global_id'],
                    'message_id' => $message['id'],
                    'notify_type' => $message['notify_type'] ?? '',
                    'created' => time(),
                ];
            }
            if (!empty($unreadMessages)) {
                // 批量添加未读消息记录
                model(ChatUnreadMessageModel::class)->addAll($unreadMessages);
            }
        }

        //update chat edited_at
        ChatService::getInstance()->updateChatEditedAt($chat['id'], $message['sent_at'], $isUpdate);
        if ($chat['link_type'] === 'task_work_order') {
            // 工单消息盒子的时间更新
            $queueData = [
                'x-userinfo' => request()->getXUserInfo(),
                'global_id' => $chat['global_id'],
                'sent_at' => $message['sent_at']
            ];
            Client::send('update_work_order_assistant_edited_at', build_queue_data_with_xu($queueData));
        }

        $receiveUserChannelList = array_column($receiveUserList, 'channel', 'channel');
        if (!empty($receiveUserChannelList)) {
            $pushMessage = [
                'chat' => $chat,
                'message' => $message
            ];
            $receiveUserChannelList = array_values($receiveUserChannelList);
            $this->centrifugalService->broadcast($receiveUserChannelList, $pushMessage);
        }
    }

    /**
     * 批量推送系统消息
     * @param $tmpMessage
     * @param $chatReceivers
     * @param $channelUserList
     * @param $chat
     * @param bool $isPush
     * @return array
     * @throws \Exception
     */
    public function batchPushSystemHitMessage($tmpMessage, $chatReceivers, $channelUserList, $chat, $isPush = true)
    {

        if (empty($tmpMessage) || empty($chatReceivers) || empty($chat)) {
            return [];
        }

        $tmpMessageData = [];
        $tmpMessage = array_sort_by($tmpMessage, 'sent_at');
        $chat = array_column($chat, null, 'global_id');
        $chatEditedAt = [];
        foreach ($tmpMessage as $tmpMessageItem) {
            $tmpMessageItem['content'] = json_encode($tmpMessageItem['content']);
            $tmpMessageItem['global_id'] = create_uuid();
            $tmpMessageData[] = $tmpMessageItem;
            if (empty($chatEditedAt[$tmpMessageItem['chat_global_id']])) {
                $chatEditedAt[$tmpMessageItem['chat_global_id']] = ['id' => $chat[$tmpMessageItem['chat_global_id']]['id'], 'edited_at' => $tmpMessageItem['sent_at']];
            } elseif ($chatEditedAt[$tmpMessageItem['chat_global_id']]['edited_at'] < $tmpMessageItem['sent_at']) {
                $chatEditedAt[$tmpMessageItem['chat_global_id']]['edited_at'] = $tmpMessageItem['sent_at'];
            }
        }
        $result = model(MessageModel::class)->addAll($tmpMessageData);
        if ($result) {
            //update chat edited_at
            if (!empty($chatEditedAt)) {
                $chatEditedAt = array_values($chatEditedAt);
                model(ChatModel::class)->saveAll($chatEditedAt);
            }
            //是否需要推送消息
            if ($isPush) {
                foreach ($tmpMessageData as $tmpMessageDataItem) {
                    if (isset($chatReceivers[$tmpMessageDataItem['chat_global_id']]) && isset($chat[$tmpMessageDataItem['chat_global_id']])) {
                        $currentReceiversChannel = [];
                        foreach ($chatReceivers[$tmpMessageDataItem['chat_global_id']] as $chatReceiversItem) {
                            $currentReceiversChannel[] = $channelUserList[$chatReceiversItem];
                        }
                        if (empty($currentReceiversChannel)) {
                            continue;
                        }
                        $currentReceiversChannel = array_unique($currentReceiversChannel);
                        $this->centrifugalService->broadcast($currentReceiversChannel, [
                            'chat' => $chat[$tmpMessageDataItem['chat_global_id']],
                            'message' => $tmpMessageDataItem
                        ]);
                    }
                }
            }
        }
    }

    /**
     * 批量添加
     * @param $data
     * @return array
     * @throws \Exception
     */
    public function addMultipleMessage($data)
    {
        $result = [];
        //数据量过大需要分块
        foreach (array_chunk($data, 100) as $item) {
            $result[] = model(MessageModel::class)->addAll($item);
        }

        return $result;
    }

    /**
     * 撤回消息
     * @param $data
     * @param $userId
     * @return array|false|mixed|string|null
     * @throws \Exception
     */
    public function revokeMessage($data, $userId)
    {
        $messageModel = model(MessageModel::class);
        $messageData = $messageModel->find($data['id']);
        $messageReply = [];
        if ($messageData['sender'] != $userId) {
            throw_strack_exception('Message retraction must be the sender', ErrorCode::MESSAGE_REVOKE_USER);
        }
        if (strtotime("+1 days", $messageData['sent_at']) < time()) {
            throw_strack_exception('The message recall time limit has expired', ErrorCode::MESSAGE_REVOKE_TIME);
        }
        $messageData['status'] = 'revoke';
        $result = $messageModel->save($messageData);
        if ($result) {
            $messageData['content'] = json_decode($messageData['content'], true);
            // 根据全局会话ID获取用户的个人消息通道
            $chatUserList = model(ChatUserModel::class)->where(['chat_global_id' => $data['chat_global_id']])->select();
            $chatUserMap = array_column($chatUserList, 'user_id');
            $userList = model(UserModel::class)->field('id,name,channel')->where(['id' => ['IN', implode(',', $chatUserMap)]])->select();
            // 如果撤回消息是回复消息，就减少主消息的被回复消息条数
            if ($messageData['content_type'] == 'reply') {
                $messageReply = model(MessageReplyModel::class)->find($messageData['message_reply_id']);
                $messageModel->execute("UPDATE message SET content = JSON_SET(IFNULL(content, '{}'), '$.\"reply_sum\"', content->>'$.reply_sum'-1) where id = {$messageReply['message_main_id']}");
            }
            // 如果撤回信息是艾特信息就修改chatUser中的config
            $remind = false;
            $remindUsers = [];
            if (!empty($messageData['content']['type']) && in_array($messageData['content']['type'], ['remind_specified_user', 'remind_all'])) {
                $remind = true;
                $contentType = $messageData['content']['type'];
                if ($contentType == "remind_all") {
                    $remindUsers = $chatUserMap;
                }
                if ($contentType == "remind_specified_user") {
                    $remindUserId = $messageData['content']['user_id'] ?? "";
                    $remindUsers = explode(',', $remindUserId);
                }
            }
            $channelList = [];
            foreach ($userList as $item) {
                if ($item['id'] != $userId) {
                    $channelList[] = $item['channel'];
                }
            }
            if ($remind) {
                $remindUsers = implode(',', $remindUsers);
                model(ChatUserModel::class)->execute("UPDATE chat_user SET config = JSON_SET(IFNULL(config, '{}'), '$.\"by@\"', 'no') where chat_global_id = '{$data['chat_global_id']}' and user_id in ($remindUsers)");
            }
            if ($channelList) {
                $this->centrifugalService->broadcast($channelList, [
                    'event_key' => "revoke_message",
                    'event_data' => [
                        "type" => $messageData['content_type'],
                        "user_id" => $userId,
                        "message_id" => $data['id'],
                        "reply_main_message_id" => $messageReply['message_main_id'] ?? 0,
                        "chat" => ChatService::getInstance()->getChatDetail(['global_id' => $data['chat_global_id']])
                    ]
                ]);
            }
        }
        return $result;
    }

    /**
     * 查询回复消息列表
     * @param $param
     * @param $currentUserId
     * @return array
     */
    public function selectReplyMessage($param, $currentUserId)
    {
        return $this->selectWithReadStatus($param, $currentUserId, false);
    }

    /**
     * 查询转发消息列表
     * @param $param
     * @return array
     */
    public function selectForwardMessage($param)
    {
        $messageModel = model(MessageModel::class);
        $order = $param['order'] ?? "message.sent_at desc";
        $page = $param['page'] ?? [1, 2];
        $fields = $param['fields'] ?? "message.*";
        $fieldsArray = explode(',', $fields);

        $data = $messageModel
            ->where($param['filter'])
            ->order($order)
            ->page($page[0], $page[1])
            ->field(implode(',', $fieldsArray))
            ->select();

        // 查询回复消息
        $messageIdList = array_column($data, null, 'id');
        $messageSenderIdList = array_column($data, 'sender');
        $messageSenderList = [];
        $replyMessageIdList = [];
        $replyMessageMap = [];
        foreach ($data as $k => $message) {
            if ($message['content_type'] === 'reply') {
                if (!array_key_exists($message['reply_message_id'], $messageIdList) && !in_array($message['reply_message_id'], $replyMessageIdList)) {
                    $replyMessageIdList[] = $message['reply_message_id'];
                } else if (array_key_exists($message['reply_message_id'], $messageIdList)) {
                    $replyMessageMap[$message['reply_message_id']] = $messageIdList[$message['reply_message_id']];
                }
            }
        }
        if (!empty($messageSenderIdList)) {
            $messageSenderList = model(UserModel::class)->where(['id' => ['IN', $messageSenderIdList]])->select();
            $userService = new UserService();
            $userAvatarList = $userService->getUserAvatar($messageSenderIdList);
            $messageSenderList = array_column($messageSenderList, 'name', 'id');
        }
        if (!empty($replyMessageIdList)) {
            $replyMessageData = $messageModel->where(['id' => ['IN', implode(',', $replyMessageIdList)]])->select();
            $replyMessageMap += array_column($replyMessageData, null, 'id');
            $replyMessageSenderIds = array_column($replyMessageData, 'sender');
            if ($replyMessageSenderIds) {
                $replyMessageSenderList = model(UserModel::class)->where(['id' => ['IN', $replyMessageSenderIds]])->select();
                $replyMessageSenderList = array_column($replyMessageSenderList, 'name', 'id');
            }
        }
        foreach ($replyMessageMap as &$replyMessageDatum) {
            $replyMessageDatum['content'] = json_decode($replyMessageDatum['content'], true);
        }
        foreach ($data as &$row) {
            $row['content'] = json_decode($row['content'], true);
            $row['sender_name'] = $messageSenderList[$row['sender']] ?? '';
            $row['avatar'] = $userAvatarList[$row['sender']] ?? '';
            if ($row['content_type'] === 'reply') {
                $row['reply_message'] = $replyMessageMap[$row['reply_message_id']] ?? null;
                $row['reply_message']['sender_name'] = $replyMessageSenderList[$row['reply_message']['sender']] ?? '';
            }
        }
        return [
            'rows' => $data
        ];
    }

    /**
     * 批量发送催一催消息
     * @param $chatIds
     * @param $chatReceivers
     * @param $currentUserId
     * @param $messageData
     * @return array
     * @throws \Exception
     */
    public function batchPushUrgeMessage($chatIds, $chatReceivers, $currentUserId, $messageData)
    {
        $messages = [];
        //给每个频道发送
        foreach ($chatIds as $chatId) {
            $tmpMessage = $messageData;
            $tmpMessage['chat_global_id'] = $chatId;
            $tmpMessage['global_id'] = create_uuid();
            $messages[] = model(MessageModel::class)->addItem($tmpMessage);
        }

        $messages = array_column($messages, null, "chat_global_id");

        $userIds = [];
        foreach ($chatReceivers as $chatReceiver) {
            $userIds = array_merge($userIds, $chatReceiver);
        }

        $userChannel = model(UserModel::class)->where(['id' => ["IN", $userIds]])->field("id,channel")->select();
        $userChannel = array_column($userChannel, 'channel', 'id');
        //消息推送
        $chats = model(ChatModel::class)->where(['global_id' => ["IN", $chatIds]])->select();
        $chatUsers = model(ChatUserModel::class)->where(['chat_global_id' => ["IN", $chatIds]])->select();
        $chatUsers = array_group_by($chatUsers, 'chat_global_id');
        foreach ($chats as $chatIndex => $chat) {
            if ($chat['type'] == "one2one") {
                $userAvatar = $this->getChatUserInfo([$currentUserId]);
                $chats[$chatIndex]['name'] = $userAvatar[0]['name'];
                $chats[$chatIndex]['avatar'] = $userAvatar[0]['thumb'] ? [$userAvatar[0]['thumb']] : [];
            } else if ($chat['type'] == "group") {
                $receivers = array_column($chatUsers[$chat['global_id']], 'user_id');
                $userAvatar = $this->getChatUserInfo(array_slice($receivers, 0, 9, false));
                $chats[$chatIndex]['avatar'] = array_column($userAvatar, 'thumb');
                foreach ($userAvatar as $userAvatarItem) {
                    $chats[$chatIndex]['chat_icon_data'][] = [
                        "id" => $userAvatarItem['id'],
                        "name" => $userAvatarItem['name'],
                        "avatar" => $userAvatarItem['thumb']
                    ];
                }
            }
            $chats[$chatIndex]['chat_global_id'] = $chat['global_id'];
        }
        $chats = array_column($chats, null, 'global_id');

        $receiveUserChannelList = [];
        $unreadMessages = [];
        foreach ($chatReceivers as $chatGlobalId => $chatReceiver) {
            if (isset($messages[$chatGlobalId]) && isset($chats[$chatGlobalId])) {
                $pushMessage = [
                    'chat' => $chats[$chatGlobalId],
                    'message' => $messages[$chatGlobalId]
                ];

                $userChannelList = [];
                foreach ($chatReceiver as $chatReceiverItem) {
                    if (isset($userChannel[$chatReceiverItem])) {
                        $userChannelList[] = $userChannel[$chatReceiverItem];
                        $unreadMessages[] = [
                            'user_id' => $chatReceiverItem,
                            'chat_global_id' => $chatGlobalId,
                            'message_id' => $messages[$chatGlobalId]['id'],
                            'notify_type' => $messages[$chatGlobalId]['notify_type'],
                            'created' => time(),
                        ];
                    }
                }
                if (!empty($userChannelList)) {
                    $receiveUserChannelList[$chatGlobalId] = ['channel' => $userChannelList, 'push_message' => $pushMessage];
                }
            } else {
                unset($messages[$chatGlobalId]);
            }
        }

        //添加未读
        if (!empty($unreadMessages)) {
            model(ChatUnreadMessageModel::class)->addAll($unreadMessages);
        }

        //发送通知
        if (!empty($receiveUserChannelList)) {
            foreach ($receiveUserChannelList as $receiveUserChannelItem) {
                $this->centrifugalService->broadcast($receiveUserChannelItem["channel"], $receiveUserChannelItem["push_message"]);
            }
        }

        return $messages;
    }

    /**
     * 发送系统通知
     * @param $messageData
     * @throws \Exception
     */
    public function sendSystemNotifyMessage($messageData)
    {
        //模板渲染参数
        $param = $messageData["param"];
        //接收者
        $receiver = $messageData["receiver"];
        //渲染模板
        $templateId = $messageData["template_id"];
        //项目
        $projectId = $messageData['project_id'] ?? 0;
        //内容类型
        $contentType = $messageData["content_type"];
        //操作
        $actions = $messageData["actions"];
        //通知类型
        $noticeType = $messageData['notice_type'];
        //是否弹窗
        $isPopUp = $messageData['is_popup'] ?? false;
        //消息类型
        $messageKey = $messageData['message_key'] ?? "";
        //额外参数
        $extraData = $messageData['extra_data'] ?? [];
        //相关详细参数
        $messageDetailData = $messageData['detail_data'] ?? [];
        //发送通知的对象
        $notifyUserMark = $messageData['notify_user_mark'] ?? "producer_assistant";

        $messageService = MessageService::getInstance();
        $renderedTemplate = $messageService->renderMsgTemplate($templateId, $param);

        $data = [
            'project_id' => $projectId,
            'receiver' => $receiver,
            'type' => "normal",
            'content_type' => $contentType,
            'content' => [
                'title' => $renderedTemplate['title'],
                'content' => $renderedTemplate['content_rendered'],
                'content_pc' => $renderedTemplate['content_pc_rendered'],
                'type' => $noticeType,
                'urls' => $actions,
                'icon' => "",
                'message_key' => $messageKey,
                'extra_data' => $extraData,
            ],
            'is_popup' => $isPopUp ? "yes" : "no"
        ];

        //队列发送


        $res = [
            'data' => $data,
            'message_detail_data' => $messageDetailData,
            'notify_user_mark' => $notifyUserMark
        ];
        Client::send('batch_send_system_notice_message', build_queue_data_with_xu($res));
    }

    /**
     * 批量转发消息
     * @param $data
     * @param $userId
     * @param $tenantId
     * @return array
     * @throws \Throwable
     */
    public function batchForwardMessage($data, $userId, $tenantId)
    {
        $chats = [];
        $chatService = new ChatService();
        $needBatchChatList['data'] = [];
        $count = 0;
        if ($data['message']['content_type'] == 'forward' && empty($data['message']['content']['forward_message_ids'])) {
            throw_strack_exception('No message data selected', ErrorCode::MESSAGE_MERGE_FORWARD_NOT_SELECT);
        }
        // 群组就直接传会话全局ID
        if (isset($data['group']) && $data['group']) {
            $count = $this->calculateNeedChatCount($data['group'], $count);
            foreach ($data['group'] as $item) {
                $chats[] = $item;
            }
        }
        // 用户组直接根据用户ID创建私聊会话
        if (isset($data['one2one']) && $data['one2one']) {
            $count = $this->calculateNeedChatCount($data['one2one'], $count);
            foreach ($data['one2one'] as $item => $value) {
                $needBatchChatList['data'][$item]['receiver'][] = $value;
                $needBatchChatList['data'][$item]['created_by'] = $userId;
            }
        }
        // 部门组根据部门ID获取到部门中的所有成员
        if (isset($data['department']) && $data['department']) {
            $this->calculateNeedChatCount($data['department'], $count);
            $chatUserService = new ChatUserService();
            $departmentUserList = $chatUserService->getDepartmentUnderUserIds($tenantId, $data['department']);
            $departmentUserList = array_values($departmentUserList);
            $needBatchChatCount = count($needBatchChatList['data']);
            foreach ($departmentUserList as $item => $value) {
                $needBatchChatList['data'][$item + $needBatchChatCount]['receiver'][] = $value;
                $needBatchChatList['data'][$item + $needBatchChatCount]['created_by'] = $userId;
            }
        }

        if ($needBatchChatList['data']) {
            $resBatchChatList = $chatService->batchCreateChat($needBatchChatList);
            foreach ($resBatchChatList as $item) {
                $chats[] = $item['global_id'];
            }
        }
        $chats = array_unique($chats);
        if (!empty($data['message']['content']['content'])) {
            $data['message']['content']['content'] = $this->stringHandling($data['message']['content']['content']);
        }
        $resSend = $this->batchSendMessage($chats, $data['message'], $userId);
        // 批量发送完消息以后，消息会话必定在会话列表的前列，只需要请求当前用户会话列表接口即可
        if ($resSend) {
            $param['param']['filter']['global_id'] = ['IN', $chats];
            $param['param']['type'] = 'forward';
            $param['param']['last_message_check'] = true;
            return $chatService->getUserChatList($userId, $tenantId, $param);
        }
    }

    /**
     * 计算需要的会话个数
     * @param $data
     * @param $count
     * @return int|void
     */
    private function calculateNeedChatCount($data, $count)
    {
        $count += count($data);
        if ($count > 50) {
            throw_strack_exception('no more than 50', ErrorCode::MESSAGE_FORWARD_CHAT_COUNT);
        }
        return $count;
    }

    /**
     * 批量发送消息
     * @param $chats
     * @param $message
     * @param $userId
     * @return bool
     * @throws \Exception
     */
    public function batchSendMessage($chats, $message, $userId)
    {
        if (!empty($message['content']['reply_sum'])) {
            unset($message['content']['reply_sum']);
        }
        $chatMessage = [];
        $chatMessageGlobalId = [];
        foreach ($chats as $chatIndex => $chat) {
            $chatMessage[$chatIndex] = $message;
            $chatMessage[$chatIndex]['chat_global_id'] = $chat;
            $chatMessage[$chatIndex]['sent_at'] = time();
            $chatMessage[$chatIndex]['sender'] = $userId;
            $chatMessage[$chatIndex]['content'] = json_encode($chatMessage[$chatIndex]['content']);
            $chatMessage[$chatIndex]['global_id'] = create_uuid();
            $chatMessageGlobalId[] = $chatMessage[$chatIndex]['global_id'];
        }

        $addResult = model(MessageModel::class)->addAll($chatMessage);
        if ($addResult) {
            $messageList = model(MessageModel::class)->where(['global_id' => ['IN', $chatMessageGlobalId]])->select();
            if ($messageList) {
                foreach ($messageList as $item) {
                    Client::send('send_message', build_queue_data_with_xu(['message_id' => $item['id'], 'x-userinfo' => request()->getXUserInfo()]));
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 获取催一催消息详情
     * @param $urgeMessageIds
     * @param $currentUserId
     * @return array
     * @throws \Exception
     */
    public function getUrgeMessageDetail($urgeMessageIds, $currentUserId)
    {
        $urgeMessageMemberList = model(UrgeMessageMemberModel::class)
            ->where(['urge_message_id' => ["IN", $urgeMessageIds], 'user_id' => $currentUserId])->select();

        $urgeMessageListIds = array_column($urgeMessageMemberList, 'urge_message_id', 'urge_message_id');

        $senderUrgeMessageIds = [];
        foreach ($urgeMessageMemberList as $urgeMessageMemberItem) {
            $urgeMessageIds[$urgeMessageMemberItem["urge_message_id"]] = $urgeMessageMemberItem["urge_message_id"];
            if ($urgeMessageMemberItem["is_sender"] === 1) {
                $senderUrgeMessageIds[] = $urgeMessageMemberItem["urge_message_id"];
            }
        }
        $urgeMessageMemberReceiverGroup = [];
        if (!empty($senderUrgeMessageIds)) {
            $urgeMessageMemberReceiverGroup = UrgeMessageService::getInstance()->getUrgeMessageMemberReceiverGroup($senderUrgeMessageIds);
        }
        return [
            "is_my_urge_message" => $urgeMessageListIds,
            "urge_message_member_receiver_group" => $urgeMessageMemberReceiverGroup
        ];
    }

    /**
     * 消息艾特字符串处理
     * @param $string
     * @return string
     */
    private function stringHandling($string)
    {
        $rightStr = explode("@>", $string);
        $forCount = count($rightStr);
        $tmpStr = [];
        foreach ($rightStr as $key => $item) {
            if ($item) {
                if (strpos($string, $item . "@>") !== false) {
                    $tmpStr[] = $item . "@>";
                    continue;
                }
            } else if ($key != ($forCount - 1)) {
                $tmpStr[] = "@>";
                continue;
            }
            $tmpStr[] = $item;
        }
        foreach ($rightStr as $item) {
            if ($item) {
                $item = str_replace(" ", "", $item);
                $item = explode("<@", $item);
                if ($item) {
                    foreach ($item as $value) {
                        if ($value) {
                            foreach ($tmpStr as &$str) {
                                if (strpos($str, "<@" . $value . "@>") !== false) {
                                    $str = str_replace("<@" . $value . "@>", "@" . $value, $str);
                                }
                            }
                        }
                    }
                }
            }
        }
        foreach ($tmpStr as &$item) {
            if (strpos($item, "@>") !== false) {
                $item = str_replace("@>", "", $item);
            }
            if (strpos($item, "<@") !== false) {
                $item = str_replace("<@", "", $item);
            }
        }
        return implode("", $tmpStr);
    }

    /**
     * 搜索聊天记录
     * @param $param
     * @return array
     * @throws \Throwable
     */
    public function searchMessageRecord($param)
    {
        $page = $param['page'] ?? [1, 10];
        $order = $param['order'] ?? 'sent_at desc';
        $filter = [
            'chat_global_id' => $param['filter']['chat_global_id'],
            'status' => ['NEQ', 'revoke'],
            'content_type' => ['IN', 'text,reply,bulletin'],
            '_string' => "json_extract(content,'$.content') like '%{$param['filter']['content']}%'"
        ];
        $messageList = model(MessageModel::class)
            ->where($filter)
            ->order($order)
            ->page($page[0], $page[1])
            ->select();
        $senderList = array_column($messageList, 'sender');
        $userList = model(UserModel::class)->field('id,name')->where(['id' => ['IN', implode(',', $senderList)]])->select();
        $userMap = array_column($userList, 'name', 'id');
        $userService = new UserService();
        $userAvatarList = $userService->getUserAvatar($senderList);
        return array_map(function ($item) use ($userMap, $userAvatarList) {
            $item['sender_name'] = $userMap[$item['sender']];
            $item['sender_avatar'] = $userAvatarList[$item['sender']];
            return $item;
        }, $messageList);
    }

    /**
     * 创建一条系统消息模板
     * @param $chat
     * @param $content
     * @return array
     */
    public function buildSystemHitMessage($chat, $content)
    {
        return [
            "chat_global_id" => $chat['global_id'],
            "type" => 'normal',
            'sender' => 0,
            'project_id' => 0,
            "content_type" => 'system_hint',
            "content" => $content
        ];
    }

    /**
     * 批量推送系统通知(一份消息通知给多个群)
     * @param array $recChatGlobalIdList
     * @param $messageContent
     * @return int
     */
    public function batchPushSystemHitMessageV2(array $recChatGlobalIdList, $messageContent)
    {
        $res = 0;
        $recChatList = model(ChatModel::class)->where(['global_id' => ['IN', $recChatGlobalIdList]])->select();
        if (empty($recChatList)) {
            return $res;
        }
        $recUserList = model(ChatUserModel::class)
            ->alias('cu')
            ->join('user u on u.id = cu.user_id')
            ->where([
                'cu.chat_global_id' => ['IN', $recChatGlobalIdList],
                'cu.is_leave' => 'no',
            ])
            ->field('u.id,cu.chat_global_id')
            ->select();
        $recUserListGrouped = array_group_by($recUserList, 'chat_global_id');

        foreach ($recChatList as $chat) {
            $recUserList = $recUserListGrouped[$chat['global_id']] ?? [];
            $message = $this->buildSystemHitMessage($chat, $messageContent);
            $queueData = [
                'chat_global_id' => $chat['global_id'],
                'message' => $message,
                'user_id_list' => array_column($recUserList, 'id'),
            ];
            Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));
            $res += 1;
        }
        return $res;
    }

    /**
     * 推送实体任务消息
     * @param $chat
     * @param $chatMessageContent
     * @return bool
     * @throws \Exception
     */
    public function pushEntityTaskChatMessage($chat, $chatMessageContent)
    {
        $chatUserList = model(ChatUserModel::class)->where(['chat_global_id' => $chat['global_id']])->select();
        if (empty($chatUserList)) {
            return false;
        }
        $chatUserIds = array_column($chatUserList, 'user_id');
        $message = $this->buildSystemHitMessage($chat, $chatMessageContent);
        $queueData = [
            'chat_global_id' => $chat['global_id'],
            'message' => $message,
            'user_id_list' => $chatUserIds
        ];
        Client::send('send_system_hit_message', build_queue_data_with_xu($queueData));
        return true;
    }

    /**
     * 批量转发消息
     * @param array $data
     * @param int $userId
     * @param int $tenantId
     * @return array
     * @throws Exception
     * @throws \Throwable
     */
    public function batchSendMessageWithReturnChat(array $data, int $userId, int $tenantId)
    {
        $chats = [];
        $chatService = ChatService::getInstance();
        $needBatchChatList['data'] = [];
        $count = 0;

        // 群组就直接传会话全局ID
        if (isset($data['group']) && $data['group']) {
            $count = $this->calculateNeedChatCount($data['group'], $count);
            foreach ($data['group'] as $item) {
                $chats[] = $item;
            }
        }
        // 用户组直接根据用户ID创建私聊会话
        if (!empty($data['one2one'])) {
            $count = $this->calculateNeedChatCount($data['one2one'], $count);
            foreach ($data['one2one'] as $value) {
                $needBatchChatList['data'][] = [
                    'receiver' => [$value],
                    'created_by' => $userId,
                ];
            }
        }
        // 部门组根据部门ID获取到部门中的所有成员
        if (!empty($data['department'])) {
            $this->calculateNeedChatCount($data['department'], $count);
            $departmentUserList = ChatUserService::getInstance()->getDepartmentUnderUserIds($tenantId, $data['department']);
            foreach ($departmentUserList as $value) {
                $needBatchChatList['data'][] = [
                    'receiver' => [$value],
                    'created_by' => $userId,
                ];
            }
        }

        if ($needBatchChatList['data']) {
            $resBatchChatList = $chatService->batchCreateChat($needBatchChatList);
            foreach ($resBatchChatList as $item) {
                $chats[] = $item['global_id'];
            }
        }
        $chats = array_unique($chats);
        if (empty($chats)) {
            throw new LogicException("you don`t select chats", ErrorCode::DATA_INVALID);
        }
        $this->batchSendMessage($chats, $data['message'], $userId);
        // 批量发送完消息以后，消息会话必定在会话列表的前列，只需要请求当前用户会话列表接口即可

        $param['param']['filter']['global_id'] = ['IN', $chats];
        $param['param']['type'] = 'forward';
        $param['param']['last_message_check'] = true;
        return $chatService->getUserChatList($userId, $tenantId, $param);
    }

    /**
     * 新版消息 稍后提醒
     * @param $param
     * @return array|false|mixed|string
     */
    public function remindMessageLater($param)
    {
        // 只针对新版消息稍后提醒
        $messageAllowedList = [
            MessageModel::CONTENT_TYPE_COMMON_POPOVER
        ];
        $message = model(MessageModel::class)
            ->where(['id' => $param['message_id'], 'content_type' => ['in', $messageAllowedList]])
            ->column('id');
        if (!empty($message)) {
            Client::send('send_message', build_queue_data_with_xu([
                'message_id' => array_shift($message),
                'notifier_restricted' => [request()->getUnionUserId()],
                'x-userinfo' => request()->getXUserInfo()
            ]), $param['delay_time']);
        }
        return $message;
    }
}
